package org.veridiandynamics.client.presenter;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.veridiandynamics.server.domain.User;

/**
 * ClientConnectionHandler is a class that will handle connecting to the 
 * server and passing/receiving information.
 * 
 * @author Lee, Will
 */
public class ClientConnectionHandler 
{
	/**
	 * login handles logging-in with the server
	 * 
	 * @param username
	 * @param password
	 * @param role
	 * @return Boolean confirmation of logging-in
	 */
	public User login(String username, String password, String role)
	{
		Map<String, Object> requestMap = new HashMap<String, Object>();
		Map<String, Object> responseMap;
		requestMap.put("requestType", "login");
		requestMap.put("username", username);
		requestMap.put("password", password);
		requestMap.put("role", role);
		
		try {
			SocketChannel clientSocket = SocketChannel.open();
			clientSocket.configureBlocking(false);
			clientSocket.connect(new InetSocketAddress(InetAddress.getLocalHost(), 8000));
			Selector selector = Selector.open();
			SelectionKey clientKey = clientSocket.register(selector, SelectionKey.OP_CONNECT);
			int BUFFER_SIZE = 4096;
			ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
			
			while (selector.select(1000) > 0) { 
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> iterator = keys.iterator();
				while(iterator.hasNext()) {
					SelectionKey key = iterator.next();
					iterator.remove();
					
					SocketChannel channel = (SocketChannel) key.channel();
					
					if(key.isConnectable()) { 
						if(channel.isConnectionPending()) {
							channel.finishConnect();
						}
						channel.register(selector, SelectionKey.OP_WRITE);
						buffer = null;
						continue;
					}
					if (key.isReadable()) {
						buffer = ByteBuffer.allocate(BUFFER_SIZE);
						channel.read(buffer);
						buffer.flip();
						if (buffer.limit() <= 0) {
							continue;
						}

						ByteArrayInputStream inputByteStream = new ByteArrayInputStream(buffer.array());
						ObjectInputStream inputObjectStream = new ObjectInputStream(inputByteStream);
						responseMap = (Map<String, Object>) inputObjectStream.readObject();
						channel.close();
						return (User) responseMap.get("user");
					}
					
					if(key.isWritable()) {
						ByteArrayOutputStream outputByteStream = new ByteArrayOutputStream();
						ObjectOutputStream outputObjectStream = new ObjectOutputStream(outputByteStream);
						outputObjectStream.writeObject(requestMap);
						buffer = ByteBuffer.allocate(BUFFER_SIZE);
						buffer = ByteBuffer.wrap(outputByteStream.toByteArray());
						channel.write(buffer);
						buffer.clear();
						channel.register(selector, SelectionKey.OP_READ);
					}
				}
			}
			
		
		} catch(IOException e)
		{
			e.printStackTrace();
		} catch(ClassNotFoundException e)
		{
			e.printStackTrace();
		}
			
		
		return null;
	}
}
